home *** CD-ROM | disk | FTP | other *** search
/ Aminet 52 / Aminet 52 (2002)(GTI - Schatztruhe)[!][Dec 2002].iso / Aminet / docs / mags / saku17.lha / Teksti / Ohjelmointi.txt < prev    next >
Text File  |  1996-03-01  |  27KB  |  659 lines

  1. 5
  2. 1*
  3.  
  4. {A                Järjestelmäohjelmoinnin alkeiskurssi - Osa 4: GUI
  5. {A                -------------------------------------------------
  6.         
  7. {7                                  Sami Klemola
  8.  
  9.  
  10. Alun perin tässä osassa, jonka olisi pitänyt tulla julkaistuksi jo hyvän
  11. aikaa sitten, oli tarkoituksena käsitellä Intuitionia edelleen, mutta teemme
  12. nyt hieman yllättävän käännöksen matkallamme kohti Amigan käyttöjärjestelmän
  13. hallintaa. Käsittelemme kyllä edelliseen osaan jatkona menut ja gadgetit eli
  14. valikot ja nappulat. Emme kuitenkaan tee niitä suoraan Intuitionin kanssa
  15. kommunikoiden, vaan tutustumme GadToolsin päälle asettuvaan GUI-kirjastoon
  16. nimeltä Triton.
  17.  
  18. GUI:n eli graafisen käyttöliittymän tekeminen helpottui sanottavasti Release
  19. 2:n myötä sen esiteltyä uuden gadtools.libraryn. Asiat ovat kuitenkin
  20. edenneet vielä siitä, ja nyt uusinta uutta ovat kolmansien osapuolien
  21. tuottamat oliopohjaiset kirjastot. Niistä ehkäpä tunnetuin on MUI, mutta se
  22. on käyttökelvoton suunnattoman muistinkulutuksensa ja järjettömän hitautensa
  23. takia.
  24.  
  25. Omaan käyttööni valitsin Tritonin, koska se on nopea ja pienikokoinen.
  26. Lisäksi sitä on helppo ohjelmoida, ja sen kanssa graafisen käyttöliittymän
  27. tekeminen on todella helppoa. Triton hoitaa kaikki yhteydet Intuitioniin ja
  28. GadToolsiin sekä tarjoaa Intuitionin peruspalveluiden ja vielä GadToolsin
  29. toimintojen lisäksi joukon omiaan. Kaikki nämä ovat Tritonin kanssa olioita,
  30. joiden käsittely on erittäin yksinkertaista.
  31.  
  32. Oliot toimivat itsenäisesti Tritonin alaisuudessa, ja niiden kanssa voidaan
  33. olla tekemisissä sen kautta. Niiden tilasta saadaan tietoja ja niiden tilaa
  34. voi muuttaa. Kun käyttäjä aktivoi olion, Triton kertoo siitä ohjelmalle
  35. lähettämällä viestin. Triton-ohjelman toiminta on viestien vastaanottamista
  36. ja niiden pohjalta toimimista. Tritonin kanssa ohjelma voi keskittyä
  37. olennaiseen, ja ohjelmoija voi tyystin unohtaa ongelmat erikokoisten
  38. kirjasinten ja ikkunan koon muuttumisen kanssa.
  39.  
  40. Triton on osittain sharewarea. Itse kirjaston käyttämisestä ohjelmien
  41. ajamiseen ja omien ohjelmien tekemiseen ei tarvitse maksaa mitään, mutta
  42. Tritoniin kuuluu Prefs-editori, jolla voidaan asetella kunkin
  43. Triton-ohjelman ikkunat sopiviksi, ja sen käytöstä pitää maksaa 15 dollarin
  44. tai 20 Saksan markan suuruinen hinta. Rekisteröity versio pitää siis
  45. muistissa ikkunoiden paikat, ja ohjelmien ikkunat aukeavat aina niin kuin
  46. olet ne viimeksi asettanut!
  47.  
  48. Tämä artikkeli ei ole kattava opastus graafisen käyttöliittymän tekemiseen
  49. Tritonilla. Itse asiassa tässä on vain pieniä tiedonpalasia sieltä täältä,
  50. mutta kunnollista kokonaisuutta ei saa muodostettua ennen kuin tutustuu
  51. lähemmin Tritonin omaan dokumentaatioon. Jossakin tulevassa osassa voimme
  52. vielä palata Tritoniin esimerkiksi olioiden läpikäymisen merkeissä, mutta
  53. toistaiseksi tietoa niistä on aika vähän. Käydään kuitenkin asiaan ja
  54. tutustumaan Tritoniin.
  55.  
  56.  
  57. {3Triton
  58.  
  59. Triton on kirjoitettu kirjastoksi, jota käytetään samalla tavalla kuin
  60. käyttöjärjestelmän omiakin kirjastoja. Kirjasto avataan normaalisti, ja sen
  61. jälkeen avataan Triton-projekti. Projekti käsittää ikkunan, jossa voi olla
  62. valikoita ja sisältönä kaikenlaisia olioita. Ne kuvataan makrojen avulla
  63. tavalla, joka tuo mieleen jonkinlaisen ohjelmoinnin opetuksessa käytetyn
  64. pseudokielen. Tritonille kerrotaan, mitä halutaan mihinkin kohtaan, ja se
  65. tekee oliot, laskee niille koon ja paikan jne. Tritonissa on "layout
  66. engine", joka toimii kaikenkokoisilla kirjasimilla ja osaa laskea olioille
  67. uuden koon ikkunan koon muuttuessa.
  68.  
  69. Kirjaston avaamiseen voit tutustua kurssin aiemmissa osissa. Tritonin
  70. avaamisen jälkeen luodaan sovellus, mikä kuuluu alkutoimenpiteisiin. Tässä
  71. on lyhyt koodi, joka tekee sen:
  72.  
  73. struct TR_App *App;
  74.  
  75.     if(App=TR_CreateAppTags(
  76.         TRCA_Name,    "MyApp",
  77.         TRCA_Release, "1.0",
  78.         TRCA_Version, "42.113",
  79.         TRCA_Date,    "3.11.94",
  80.         TAG_END)) {
  81.  
  82.         /* Avattu */
  83.  
  84.         TR_DeleteApp(App);
  85.     } else {
  86.  
  87.        /* Virhe */
  88.  
  89.     }
  90.  
  91. Helpompi tapa kuitenkin on käyttää triton.lib-apukirjastossa olevia
  92. TR_OpenTriton()- ja TR_CloseTriton()-funktioita, jotka tekevät molemmat, eli
  93. TR_OpenTriton() avaa ensin kirjaston ja luo sitten sovelluksen. Sovellus on
  94. struct Application, jossa Triton pitää kaikki ohjelmaasi koskevat tiedot.
  95. Sovellukseen voidaan myöhemmin avata yksi tai useampia projekteja. Projekti
  96. on nykyään sama kuin yksi Triton-ikkuna. Projektin määrittelyssä kuvataan
  97. ensin ikkunan ominaisuudet, sitten valikot ja lopuksi ikkunan sisältö.
  98. Esimerkki projektin avaamisesta:
  99.  
  100. struct TagItem dummyTags = {
  101.     TRWI_Title, (ULONG) "A dummy window",
  102.     TRWI_ID, 42,
  103.     TAG_END
  104. };
  105.  
  106. void dummyFunction(void) {
  107. struct TR_Project *dummyProject;
  108.  
  109.     if(dummyProject=TR_OpenProject(Application,dummyTags)) {
  110.  
  111.         /* Onnistui */
  112.  
  113.         TR_CloseProject(dummyProject);
  114.     } else {
  115.  
  116.         /* Virhe */
  117.  
  118.     }
  119. }
  120.  
  121. Projektilla tulee olla yksilöllinen tunniste (TRWI_ID). Sen pitää olla muu
  122. kuin nolla, ja sen pitää pysyä samana. Triton tallentaa ikkunan koon ja muut
  123. parametrit, joten ne hukkuvat, jos ID muuttuu joskus. Yllä olevassa koodissa
  124. on staattinen taglista projektin kuvaamiseen. Triton ei tue
  125. TAG_MORE-toimintoa, joten listoja ei voi yhdistellä. Joskus voi olla tarpeen
  126. käyttää TR_OpenProjectTags()-kutsua sen sijaan, jolloin taglista rakennetaan
  127. dynaamisesti ja ajoaikaisesti pinoon. Tämä tietysti kuluttaa paljon
  128. pinomuistia sekä pidentää ja hidastaa ohjelmaa, joten kovin pitkiä
  129. taglistoja ei kannata näin rakennella.
  130.  
  131. Yllä olevissa koodeissa käytetään tagien nimiä, mutta paljon selkeämpi
  132. tapakin taglistojen tekemiseen on olemassa: makrot. Niillä voidaan kuvata
  133. melkein kaikki tarpeellinen. Esimerkiksi ikkuna kuvataan näin:
  134.  
  135.            WindowTitle("A dummy window"),
  136.            WindowID(42),
  137.            EndProject
  138.  
  139. Myös olioille ja valikkovalinnoille on olemassa makrot. Tarkemmin
  140. määrittelyjen tekeminen ja makrojen käyttäminen siinä selviää artikkelin
  141. lopussa olevasta ohjelmaesimerkistä.
  142.  
  143. {2Oliot
  144.  
  145. Tritonin toiminta perustuu olioihin ja ohjelman käyttäjän kanssa käymä
  146. kommunikaation niiltä saataviin viesteihin. Tässä on aluksi luettelo
  147. kaikista Triton-olioista:
  148.  
  149.     Button          BOOPSI button gadget
  150.     CheckBox        GadTools CheckBox
  151.     Cycle           GadTools Cycle and MX gadget
  152.     DropBox         AppIcon dropping box
  153.     FrameBox        Framing or grouping box
  154.     Group           Triton's layout engine
  155.     Image           Image
  156.     Line            3D line
  157.     Listview        GadTools Listview
  158.     Palette         GadTools Palette gadget
  159.     Progress        Progress indicator
  160.     Scroller        GadTools Scroller
  161.     Slider          GadTools Slider
  162.     Space           Empty space
  163.     String          GadTools String gadget
  164.     Text            Text
  165.  
  166. Taulukko 1. Triton-oliot.
  167.  
  168. Näistä muutamat ovat yksinkertaisia: Text näyttää tekstiä, Line tekee viivan
  169. ja niin edelleen. Sitten on todella monimutkaisia ja kehittyneitä olioita
  170. kuten palettigadget, Listview-gadget ja Progress indicator eli valmiiksi
  171. rakennettu edistysosoitin, jossa on tiettyyn suuntaan työn etenemisen mukaan
  172. virtaava palkki, joten käyttäjä näkee, missä vaiheessa työ on. Group-olio
  173. liittyy Tritonin layout engineen. Sen avulla voidaan ohjata olioiden
  174. sijoittelua ikkunaan. Niitä voidaan ryhmitellä pysty- ja vaakasuunnassa,
  175. keskittää ja jaotella eri tavoin. Tässä jutussa en käy olioita läpi
  176. yksityiskohtaisesti, mutta lopun lähdekoodissa on hieman asiaa niistä.
  177. Asiaan voidaan palata jatkossa.
  178.  
  179. Olioilla on attribuutteja, joiden arvo voidaan lukea funktiolla
  180. TR_GetAttribute(). Niitä voidaan myös asettaa funktiolla TR_SetAttribute().
  181. Joidenkin olioiden kaikkia attribuutteja ei voida muuttaa jälkikäteen, vaan
  182. arvot ovat pysyviä, kun ne luomishetkellä on määritelty. Tällaisia
  183. muuttamattomia attribuutteja on esimerkiksi Listview-gadgetin entrylista.
  184.  
  185. {2Viestit
  186.  
  187. Tritonilta saadaan monenlaisia viestejä. Se voi kertoa ikkunan sulkunappulan
  188. painamisesta tai sisäisestä virheestä. Tärkeimmät viestit ovat NEWVALUE ja
  189. ACTION. Ne ovat olioiden lähettämiä viestejä ja kertovat, että käyttäjä on
  190. tehnyt niille jotakin. Nappulaa voi olla painettu tai vieritintä vieritetty.
  191. Viestiin sisältyy tarkka tieto siitä, mitä on tapahtunut. Triton-ohjelman
  192. toiminta perustuu viestien vastaanottamiseen ja niiden tulkintaan. Yksi
  193. lähdekoodi kertoo enemmän kuin kaksituhatta tavua, joten tämäkin selviää
  194. parhaiten esimerkkikoodista.
  195.  
  196. Myös oliot keskustelevat Tritonin kanssa viesteillä. Näiden viestien kanssa
  197. sovellus ei kuitenkaan ole yleensä tekemisissä. Sen sijaan esimerkiksi
  198. TR_SetAttribute()-funktion kutsuminen saa Tritonin lähettämään kohdeoliolle
  199. asianmukaisen viestin. Olioille voi kyllä lähettää suoraankin viestejä,
  200. mutta se ei ole yleensä tarpeen. Kaikki kanssakäyminen niiden kanssa voidaan
  201. toteuttaa helposti Tritonin kautta.
  202.  
  203. {2Help
  204.  
  205. Tritonissa on kaksi apua-toimintoa. QuickHelp-toiminto ollessaan päällä
  206. näyttää ruudulla pieniä aputekstejä, kun hiiren osoitin on sellaisen olion
  207. päällä, jolle on sellainen määritelty. Monet oliot eivät kuitenkaan tue tätä
  208. toimintoa vielä. Ohjelmaesimerkissä QuickHelp on päällä oletuksena ja sen
  209. tilaa voi muuttaa valikosta. Ylemmässä nappulassa on määriteltynä pieni
  210. aputeksti. Alempaan cycle-gadgetiin ei sellaista saa, koska kyseinen olio
  211. kuuluu niihin, jotka eivät peri attribuutteja yläluokilta. QuickHelp kun on
  212. abstraktin DisplayObject-luokan attribuutti eikä GUI-olioiden itsensä.
  213.  
  214. Toinen tapa on manuaalinen helppi. Jos projektimäärittelyssä on TWRF_HELP
  215. päällä, Triton lähettää TRMS_HELP-viestin joka kerta, kun käyttäjä painaa
  216. Help-näppäintä. Sen jälkeen on sinun vastuullasi näyttää käyttäjälle hänen
  217. haluamaansa apua. Tavallisinta on avata ohjelman AmigaGuide-dokumentti siitä
  218. kohtaa, jossa käsitellään sitä asiaa. Viestin ID-kentässä on sen olion
  219. tunniste, josta käyttäjä haluaa tietoa.
  220.  
  221. {2Loppusanat
  222.  
  223. Tarkempaa tietoa Triton-ohjelmoinnista saat
  224. Developer/TritonDev.guide-dokumentista ja Tritonin includetiedostosta sekä
  225. autodoceista. Niissä on selitetty kaikki kirjastoon liittyvät asiat. Tämän
  226. artikkelin ei missään nimessä ollutkaan tarkoitus olla tyhjentävä selvitys
  227. Triton-ohjelmoinnista. Siihen ei millään olisi aikaa eikä tilaa. Monia
  228. kysymyksiä jää auki ja monet asiat ehkäpä sekaviksi, mutta lukemalla
  229. Tritonin ohjeita ne selviävät. Tarkoitukseni olikin lähinnä tarjota helppo
  230. johdanto tähän kiehtovaan GUI-maailmaan, jonka tarjoaa Triton!
  231.  
  232.  
  233. {3Ohjelmakoodia
  234.  
  235. Tässä on kätevä ohjelmarunko, josta voi todella nopeasti tehdä pienen
  236. ohjelman. Siinä on kaikki tarvittava AmigaDOS-standardisen ohjelman
  237. tekemiseksi. Se käsittelee argumentit, sisältää cleanup-koodin sekä
  238. tarvittavan koodin virheilmoituksen näyttämiseen. Korvaa alussa kommentissa
  239. ja versiomerkkijonossa oleva "`"-merkki ohjelman nimellä (kätevästi esim.
  240. Edissä "2e/`/Ohjelma"), laita ohjelman argumenttikuvaus
  241. template-merkkijonoon ja ala kirjoittaa koodia! Puitteet ovat valmiit.
  242.  
  243. Koodi käyttää _main()-entrypointtia, kuten yleensäkin, koska sillä päästään
  244. eroon monesta kilosta turhaa koodia, esimerkiksi C-kääntäjän argumenttien
  245. parseamisesta, joka on AmigaDOS-ympäristössä tarpeetonta. Koodi käyttää sen
  246. tekemiseen DOS-funktiota ReadArgs(), johon tutustumme lähemmin kurssin
  247. tulevissa osissa. ReadArgs() käsittelee argumentit standardilla tavalla, ja
  248. se myös varmistaa, että saat tarvitsemasi argumentit. Jos niitä ei ole
  249. annettu, koodi tulostaa virheilmoituksen ja palauttaa sinut shelliin.
  250.  
  251. Käytettävissäsi on myös ohjelman nimi cmd-puskurissa. Sitä käytetään
  252. virheilmoitusten näyttämiseen, ja koodi kysyy sen ensi töikseen DOSilta.
  253. Argumentit ovat args-taulukossa, ensimmäisessä alkiossa ensimmäinen jne.
  254. Mikäli argumentti on merkkijono, alkiossa on osoitin siihen. Jos se on
  255. numeraalinen, alkio on nolla, jos sitä ei ole annettu (mikäli sen voi jättää
  256. antamatta), tai OSOITIN longwordiin, jossa on argumentin arvo. Argumentit
  257. kuvataan nk. templatella, jonka AmigaDOS-ohjelmat kertovat antamalla
  258. ainoaksi argumentiksi kysymysmerkin.
  259.  
  260. Template voi olla esimerkiksi "FILE/A,LENGTH/N". Tällöin FILE on ensimmäinen
  261. argumentti ja merkkijono. LENGTH on toinen ja numeraalinen. Argumentin nimen
  262. perässä tulevat kirjaimet kertovat sen tyypin. A tarkoittaa pakollista
  263. argumenttia. Jos se puuttuu, ohjelma ei lähde käyntiin. N tarkoittaa
  264. numeraalista argumenttia. LENGTH-argumentissa ei ole A-määrittelyä, joten se
  265. ei ole pakollinen. Jos sitä ei anneta, args[1] on nolla. Määrittelyjä voi
  266. yhdistää, ja esimerkiksi pakollinen numeraaliargumentti olisi "/N/A". Kaikki
  267. määrittelyt on selitetty Using The System Software -kirjassa sivulla 8-5
  268. (sekä enemmän ohjelmoijan näkökulmasta dos.libraryn autodoceissa
  269. ReadArgs()-funktion yhteydessä). Kerron niistä vielä lisää kurssin DOSia
  270. käsittelevässä osassa.
  271.  
  272. /* `.c */
  273.  
  274. #include "exec/io.h"
  275. #include "exec/memory.h"
  276. #include "exec/libraries.h"
  277. #include "exec/execbase.h"
  278. #include "dos/dos.h"
  279. #include "proto/exec_protos.h"
  280. #include "proto/dos_protos.h"
  281.  
  282. #define TRUE 1
  283. #define FALSE 0
  284.  
  285. typedef unsigned char u_char
  286.  
  287. int _main(void);
  288. void error(u_char *),cleanup(void);
  289.  
  290. struct RDArds *ra;
  291.  
  292. ULONG args[2];
  293.  
  294. u_char template[]="",ver[]="$VER: ` 1.00",cmd[32];
  295.  
  296. int _main(void) {
  297. LONG i;
  298.     GetProgramName(cmd,32);
  299.     if(!(ra=ReadArgs((STRPTR)template,args,NULL))) {
  300.         PrintFault(i=IoErr(),cmd);
  301.         exit(i);
  302.     }
  303.  
  304.     /* Tähän koodi. */
  305.  
  306.     cleanup();
  307.     return(RETURN_OK);
  308. };
  309.  
  310. void error(u_char *str) {
  311.     printf("%s: %s\n",cmd,str);
  312.     cleanup();
  313.     exit(RETURN_FAIL);
  314. };
  315.  
  316. void cleanup(void) {
  317.     if(ra) FreeArgs(ra);
  318. };
  319.  
  320. {2Toimiva GUI-ohjelma
  321.  
  322. Nyt tulee kurssin ensimmäinen täydellinen lähdekoodi, joka kääntyy täydeksi
  323. ohjelmaksi. Mitään se ei kyllä tee, mutta se rakentaa yksinkertaisen
  324. graafisen käyttöliittymän, ja koodista voi kommentoinnin myötävaikutuksella
  325. oppia paljon Tritonin käyttämisestä. Lähdekoodin osia tai koko koodiakin saa
  326. käyttää omissa ohjelmissaan. Maininta sen alkuperästä on kyllä suotavaa.
  327. Voit joutua muuttamaan koodista pieniä osia kuten
  328. prototyyppimäärittelytiedostojen nimiä tai muiden include-tiedostojen
  329. hakemistoja tai muuta sellaista saadaksesi sen kääntymään. Koodi kuitenkin
  330. kääntynee sellaisenaan. Itse käänsin sen DICE:llä ja GCC:llä.
  331.  
  332. Koodi on alun perin kirjoitettu edellä nähdyn yleispohjan päälle. Nyt tästä
  333. koodista saa rungon GUI-ohjelmalle. Projektimäärittelyjä ja pääsilmukan
  334. toimintoja muuttamalla voi helposti tehdä ohjelman, jossa on hieno graafinen
  335. käyttöliittymä. Jos haluat koodista dokumentoimattoman version, jota ei ole
  336. myöskään pilkottu useammille riveille, saat sen minulta pyytämällä. Avustan
  337. myös boksissani henkilökohtaisesti ohjelmointiteknisissä ongelmatilanteissa.
  338.  
  339.  
  340. /* TritonCode.c */
  341.  
  342. /* Tämä lähdekoodi on pohja mille tahansa ohjelmalle, jossa on graafinen
  343.    käyttöliittymä. Koodista voi helposti rakennella valmiin ohjelman. */
  344.  
  345. #include "exec/io.h"
  346. #include "exec/memory.h"
  347. #include "exec/libraries.h"
  348. #include "exec/execbase.h"
  349. #include "dos/dos.h"
  350. #include "libraries/triton.h"
  351. #include "proto/exec_protos.h"
  352. #include "proto/dos_protos.h"
  353. #include "proto/triton_protos.h"
  354.  
  355. #define TRUE 1
  356. #define FALSE 0
  357.  
  358. typedef unsigned char u_char
  359.  
  360. /* Tämä on oma Triton-oliomäärittelymakroni. Se on CenteredButton, johon
  361.    on ujutettu mukaan help-stringi. Alun perin se on ollut yhdellä rivillä,
  362.    ja se kannattaa siihen muotoon palauttaa. Silloin voi ottaa pois rivien
  363.    lopuissa olevat kenoviivat, jotka saavat kääntäjän jättämään seuraavan
  364.    rivinvaihdon huomiotta, mikä on tarpeen, koska makromäärittelyn pitää
  365.    olla samalla rivillä. Näinkin se toimii, mutta hyvältä se ei näytä. */
  366.  
  367. #define CenteredButtonHelp(t,i,str) HorizGroupSC,Space,TROB_Button,0L,\
  368.     TRAT_Text,(ULONG)(t),TRAT_ID,(i),TRDO_QuickHelpString,((ULONG)(str)),\
  369.     Space,EndGroup
  370.  
  371. int _main(void);
  372. void DoStuff(void),error(u_char *),cleanup(void);
  373.  
  374. struct RDArds *ra;
  375. struct TR_Project *project;     /* Osoitin Triton-projektiin */
  376. struct TR_Message *trmsg;       /* Vastaanotettu viesti */
  377.  
  378. ULONG args[2];
  379.  
  380. /* Yleisiä merkkijonoja, versio, virheilmoitukset jne. Ohjelman nimi
  381.    on s_prg:ssä, jota käytetään ohjelmassa aina, kun sitä tarvitaan. */
  382.  
  383. u_char template[]="",ver[]="$VER: TritonCode 1.00",cmd[32],
  384.     err_gui[]="unable to create GUI",s_prg[]="TritonCode";
  385.  
  386. /* Kiertonappulan vaihtoehdot. Nämä merkkijonot kiertävät nappulassa
  387.    aina kun sitä painetaan. */
  388.  
  389. u_char *CycleEntries[] = {
  390.     "Poutaa","Pilvistä","Sadetta","Myrskyä",0
  391. };
  392.  
  393. /* Nämä ovat ohjelmassa käytettävien Triton-olioiden tunnistenumerot.
  394.    Ensimmäiset kolme ovat valikkovalintoja ja loput ikkunassa olevia
  395.    nappuloita. Pidän ne eri kymmenluvuilla selvyyden vuoksi. */
  396.  
  397. #define ID_About    1
  398. #define ID_Help     2
  399. #define ID_Quit     3
  400. #define ID_Ask      10
  401. #define ID_Cycle    11
  402.  
  403. /* Tämä on Triton-projektin määrittely. Se kuvaa projektin käyttämän
  404.    ikkunan, valikot ja ikkunan sisällön eli nappulat ja muut jutut. */
  405.  
  406. ProjectDefinition(prod) {
  407.     WindowID(1),
  408.     WindowPosition(TRWP_CENTERSCREEN),
  409.     WindowTitle("TritonCode 1.00"),
  410.  
  411.     BeginMenu("Project"),               /* Valikko */
  412.     MenuItem("A_About",ID_About),       /* Ensimmäinen valinta */
  413.     MenuItemCC("H_Autohelp",ID_Help),   /* CheckMark-valinta */
  414.     ItemBarlabel,                       /* Välirivi */
  415.     MenuItem("Q_Quit",ID_Quit),         /* Hotkey rcommand-Q */
  416.  
  417.     /* Ikkunan sisältö. Pitää alkaa ryhmäoliolla. */
  418.  
  419.         VertGroupA,
  420.             SpaceB, /* Iso väli */
  421.  
  422.  
  423.             /* Keskitetty nappula, johon kuuluu aputeksti */
  424.  
  425.             CenteredButtonHelp("Kysymys",ID_Ask,
  426.                 "Vastaa hassuun kysymykseen"),
  427.  
  428.             SpaceB,HorizSeparator,SpaceB, /* Välit ja vaakaviiva */
  429.  
  430.             /* Vaakasuuntainen ryhmä, jossa on ensin teksti vasemmalla ja
  431.                sitten cycle-gadget oikealla. Cycle-gadget on tehty makron
  432.                sijaan suoraan tageja käyttämällä. */
  433.  
  434.             HorizGroupEAC,SpaceB,
  435.                 TextN("Säätila"),SpaceB,TROB_Cycle,(ULONG)CycleEntries,
  436.                 TRAT_ID,ID_Cycle,TRAT_Value,0,
  437.             SpaceB,EndGroup,
  438.  
  439.             SpaceB,
  440.         EndGroup,
  441.  
  442.     EndProject
  443. };
  444.  
  445. /* Tämä määrittely kuvaa About-valitsimen. BeginRequester() määrittelee
  446.    valitsimen otsikon ja sijainnin, tässä se tulee ruudun otsikkorivin
  447.    alle. Valitsin koostuu viidestä rivistä tekstiä sekä yhdestä eroke-
  448.    viivasta eli "horisontaalisesta separaattorista". Lopuksi määritellään
  449.    valitsimen nappulat, joita on tässä vain yksi, jonka ainoa tarkoitus
  450.    on sulkea valitsin. Mitään tietoa tämä valitsin ei käyttäjältä
  451.    ohjelmalle välitä. Nappula on keskitetty, ja siihen voi vastata myös
  452.    Returnilla (R) ja Escapella (E). Myös "O" käy. Nappulan nimessä oleva
  453.    alaviiva tekee sitä seuraavasta kirjaimesta nappulan hotkeyn. */
  454.  
  455. ProjectDefinition(abouttags) {
  456.     BeginRequester("About...",TRWP_BELOWTITLEBAR),
  457.  
  458.     VertGroupA, Space,  CenteredText3("TritonCode 1.00"),
  459.                 SpaceS, CenteredText("©1996 by Sami Klemola"),
  460.                 Space,  HorizSeparator,
  461.                 Space,  CenteredText("This program is using the"),
  462.                 SpaceS, CenteredText("Triton GUI creation system"),
  463.                 SpaceS, CenteredText("which is © by Stefan Zeiger"),
  464.                 Space,  EndGroup,
  465.  
  466.     BeginRequesterGads,
  467.     CenteredButtonRE("_Ok",1),
  468.     EndRequester
  469. };
  470.  
  471. /* Toinen valitsin pomppaa ruudulle, tällä kertaa keskelle sitä, kun
  472.    painetaan Kysymys-nappulaa. Tähän valitsimeen voi vastata kahdella
  473.    tavalla, joten meillä on kaksi nappulaa. Se vaatii hieman enemmän työtä
  474.    kuin yhden nappulan laittaminen. Niihinkin voi vastata hotkeyllä. Tämän
  475.    valitsimen näytettyään funktio palauttaa sen nappulan tunnisteen, joka
  476.    valittiin. Valitsimen tunnisteet eivät ole samaa sarjaa ikkunassa
  477.    olevien kanssa, joten tässä ne ovat yksi ja nolla. */
  478.  
  479. ProjectDefinition(asktags) {
  480.     BeginRequester("Kysymys",TRWP_CENTERSCREEN),
  481.  
  482.     VertGroupA, Space,
  483.             CenteredText("Jotkut ihmiset ovat sitä mieltä, että"),
  484.                 SpaceS,
  485.             CenteredText("heidän päänsä ympärillä on jotakin."),
  486.                 SpaceS,
  487.             CenteredText("Tuntuuko sinusta, että vanne puristaa päätäsi?"),
  488.                 Space,  EndGroup,
  489.  
  490.     BeginRequesterGads,
  491.     LineArray,BeginLine,
  492.         Space,
  493.             CenteredButtonR("_Kyllä",1),
  494.         Space,
  495.             CenteredButtonE("_Ei kai",0),
  496.         Space,
  497.     EndLine,EndArray,
  498.     EndRequester
  499. };
  500.  
  501. /* Pääohjelma avaa Tritonin ja Triton-projektin sekä asettaa pika-avun
  502.    päälle heti. TR_OpenTriton()-funktiolle annetaan tiedot ohjelmasta.
  503.    Niitä voi katsella Tritonin Prefs-editorilla. */
  504.  
  505. int _main(void) {
  506. LONG i;
  507.     GetProgramName(cmd,32);
  508.     if(!(ra=ReadArgs((STRPTR)template,args,NULL))) {
  509.         PrintFault(i=IoErr(),cmd);
  510.         exit(i);
  511.     }
  512.     if(!(TR_OpenTriton(TRITON11VERSION,
  513.         TRCA_Name,s_prg,TRCA_LongName,s_prg,    /* Ohjelman nimi */
  514.         TRCA_Info,(ULONG)"GUI Demo",            /* Ohjelman kuvaus */
  515.         TRCA_Version,(ULONG)"1.00",             /* Versionumero */
  516.         TRCA_Release,(ULONG)"1",                /* Julkaisu */
  517.         TRCA_Date,(ULONG)"1-Mar-96",TAG_END)))  /* Päiväys */
  518.         error("triton.library needed");
  519.     if(!(project=TR_OpenProject((struct TR_App *)Application,prod)))
  520.         error(err_gui);
  521.     TR_SetAttribute(project,0,TRWI_QuickHelp,TRUE);
  522.     DoStuff();
  523.     cleanup();
  524.     return(RETURN_OK);
  525. };
  526.  
  527. /* DoStuff() on pääsilmukka, joka perustuu Tritonin lähettämien viestien
  528.    vastaanottamiseen ja tulkintaan sekä niiden pohjalta toimimiseen. */
  529.  
  530. void DoStuff(void) {
  531.     while(TRUE) {
  532.         while(trmsg=(struct TR_Message *)TR_GetMsg(Application)) {
  533.  
  534.  
  535. /* Saapuneet viestit käsitellään luokkakohtaisesti. */
  536.  
  537.             switch(trmsg->trm_Class) {
  538.  
  539. /* Ikkunan sulkunappulaa on painettu. Vastataan kaikkiin viesteihin ja
  540.    poistutaan. Triton tosin vapauttaa itsekin viesteille varatun muistin,
  541.    mutta ei välttämättä viesteihin liittyviä resursseja, joten tällainen
  542.    ReplyMsg()-silmukka on hyvä olla. */
  543.  
  544.                 case TRMS_CLOSEWINDOW:
  545.                     TR_ReplyMsg(trmsg);
  546.                     while(trmsg=(struct TR_Message *)
  547.                         TR_GetMsg(Application)) TR_ReplyMsg(trmsg);
  548.                     return();
  549.  
  550. /* Tritonissa on sattunut virhe. Lienee harvinaista. Periaatteessa ilmoitus
  551.    pitäisi näyttää valitsimessa, mutta tulostaminen stdoutiinkin
  552.    käynee, koska tätä ei pitäisi tapahtuakaan. */
  553.  
  554.                 case TRMS_ERROR:
  555.                     printf("%s: %s\n",cmd,
  556.                         TR_GetErrorString(trmsg->trm_Data));
  557.                     break;
  558.  
  559. /* NEWVALUE-viestit kertovat olion tilan muuttumisesta. Tällaisen viestin
  560.    lähettävät esimerkiksi TOGGLE-tyyppiset (CHECKMARK) valikkovalinnat,
  561.    kuten tässä ohjelmassa Autohelp, sekä Listview- ja Cycle-gadgetit. Olion
  562.    uusi arvo on viestin datakentässä. */
  563.  
  564.                 case TRMS_NEWVALUE:
  565.                     switch(trmsg->trm_ID) {
  566.                         case ID_Help:
  567.                             TR_SetAttribute(project,0,TRWI_QuickHelp,
  568.                                 trmsg->trm_Data);
  569.                             break;
  570.  
  571. /*                      Tässä kohtaa pitäisi tietysti olla "case ID_Cycle:",
  572.                         jossa käsiteltäisiin säätilan vaihtuminen. Toinen
  573.                         mahdollisuus on toki se, että jos kyseessä on
  574.                         sellainen valinta, että sitä tarvitaan vasta
  575.                         tietyssä vaiheessa, ei tällaista tarvita, vaan
  576.                         tietoa tarvittaessa käytetään TR_GetAttribute()-
  577.                         funktiota olion tilan selvittämiseen. Tähän
  578.                         esimerkkiin en kumpaakaan ole laittanut tilaa
  579.                         viemään ja sekoittamaan ihmisiä. */
  580.  
  581.                     }
  582.                     break;
  583.  
  584. /* ACTION-viestin synnyttää esimerkiksi tavallinen nappula, tässä ohjelmassa
  585.    Kysymys-gadget, sekä tavallinen menuvalinta, jolla käynnistetään jokin
  586.    toiminto. Alla käsitellään kaikki tämän ohjelman kolme ACTION-tyyppisiä
  587.    viestejä heittelevää oliota. Olioiden kuvaavat tunnistenumerot ovat avuksi
  588.    toimintojen selvittämiseksi koodista. About-menuvalinnasta aukeaa
  589.    tavalliseen tapaan pieni valitsin, joka näyttää ohjelmasta tietoja.
  590.    Valitsin on suoraan kopioitu Tritonin demokoodista, mutta tekstejä on
  591.    tietysti hieman vaihdettu. Quit-valinta aikaansaa saman kuin ikkunan
  592.    sulkunappulan painaminen, eli vastataan kaikkiin viesteihin ja poistutaan.
  593.    Oikeassa ohjelmassa tässä pitäisi olla vielä valitsin, joka kysyisi,
  594.    haluaako käyttäjä varmasti poistua ja antaisi hänelle vielä Cancel-option.
  595.    Ask-nappulan toteutus on samantapainen kuin About-valikkovalinnan. Se
  596.    näyttää valitsimen, ja oikea koodi tietysti katsoisi funktion palauttaman
  597.    arvon, koska se sisältää tiedon siitä, mitä nappulaa käyttäjä painoi
  598.    valitsimen sulkemiseksi. */
  599.  
  600.                 case TRMS_ACTION:
  601.                     switch(trmsg->trm_ID) {
  602.                         case ID_About:
  603.                             TR_AutoRequest(Application,project,abouttags);
  604.                             break;
  605.                         case ID_Quit:
  606.                             TR_ReplyMsg(trmsg);
  607.                             while(trmsg=(struct TR_Message *)
  608.                                 TR_GetMsg(Application)) TR_ReplyMsg(trmsg);
  609.                             return();
  610.                         case ID_Ask:
  611.                             TR_AutoRequest(Application,project,asktags);
  612.                             break;
  613.                     }
  614.                     break;
  615.             }
  616.  
  617. /* Kun viesti on käsitelty, tai ohitettu, jos se ei ollut haluttua tyyppiä,
  618.    vaan esimerkiksi TRMS_KEYPRESSED, joka kertoo näppäimen painamisesta ja
  619.    joita tässä ohjelmassa ei käsitellä, siihen vastataan, ja sen jälkeen
  620.    jäädään odottamaan uutta viestiä. */
  621.  
  622.             TR_ReplyMsg(trmsg);
  623.         }
  624.         TR_Wait(Application,0);
  625.     }
  626. };
  627.  
  628. /* Tämä funktio tulostaa virheilmoituksen tavanomaiseen AmigaDOS-tapaan,
  629.    eli formaatti on "ohjelma: virhe". Funktio käyttää _main()-funktion
  630.    alussa DOSilta kysymäänsä nimeä. */
  631.  
  632. void error(u_char *str) {
  633.     printf("%s: %s\n",cmd,str);
  634.     cleanup();
  635.     exit(RETURN_FAIL);
  636. };
  637.  
  638. /* Tätä funktiota kutsutaan aina ohjelmasta poistuttaessa. Tässä ohjelmassa
  639.    ei ole paljon siivottavaa, joten funktio sulkee vain Triton-projektin ja
  640.    sitten Tritonin itsensä. Lopuksi vapautetaan argumentit, joita tässä
  641.    ohjelmassa ei tosin käytetäkään. */
  642.  
  643. void cleanup(void) {
  644.     if(project) TR_CloseProject(project);
  645.     TR_CloseTriton();
  646.     if(ra) FreeArgs(ra);
  647. };
  648.  
  649.  
  650. {3Mitä seuraavaksi?
  651.  
  652. Jatkoa seuraa ensi numerossa. En ole vielä päättänyt, mikä seuraavan osan
  653. aihe on, mutta se selviää todennäköisesti viimeistään silloin, kun se on
  654. valmis. Todennäköisesti on aika alkaa käsitellä DOS-kirjastoa, koska se
  655. tarjoaa paljon kaikkien ohjelmien tarvitsemia palveluita. Samalla tai ehkä
  656. jatkossa pitää myös paneutua enemmän aikaisemmissa osissa liian nopeasti
  657. käsiteltyihin asioihin. Lähdekoodia on luvassa myös jatkossa. Palautettakin
  658. otetaan vastaan.
  659.